home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / util / CompactInputStream.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  9.1 KB  |  353 lines  |  [TEXT/CWIE]

  1. // CompactInputStream.java
  2. // By Ned Etcode
  3. // Copyright 1995, 1996, 1997 Netscape Communications Corp.  All rights reserved.
  4.  
  5. package netscape.util;
  6.  
  7. import java.io.*;
  8.  
  9. /** @private
  10.   */
  11. public class CompactInputStream extends InputStream {
  12.     static final int INVALID_BUFFER_COUNT = 8;
  13.  
  14.     InputStream in;
  15.     int booleanCount = INVALID_BUFFER_COUNT;
  16.     int booleanBuffer;
  17.     Vector stringVector = new Vector(128);
  18.  
  19.     public CompactInputStream(InputStream in) {
  20.         super();
  21.         this.in = in;
  22.     }
  23.  
  24.     public int read() throws IOException {
  25.         booleanCount = INVALID_BUFFER_COUNT;
  26.         return in.read();
  27.     }
  28.  
  29.     public int read(byte value[]) throws IOException {
  30.         booleanCount = INVALID_BUFFER_COUNT;
  31.         return in.read(value, 0, value.length);
  32.     }
  33.  
  34.     public int read(byte value[], int offset, int length) throws IOException {
  35.         booleanCount = INVALID_BUFFER_COUNT;
  36.         return in.read(value, offset, length);
  37.     }
  38.  
  39.     public long skip(long n) throws IOException {
  40.         if (n > 0) {
  41.             booleanCount = INVALID_BUFFER_COUNT;
  42.             return in.skip(n);
  43.         }
  44.  
  45.         return n;
  46.     }
  47.  
  48.     public int available() throws IOException {
  49.         return in.available();
  50.     }
  51.  
  52.     public void close() throws IOException {
  53.         booleanCount = INVALID_BUFFER_COUNT;
  54.         in.close();
  55.     }
  56.  
  57.     public void mark(int readlimit) {
  58.     }
  59.  
  60.     public void reset() throws IOException {
  61.         throw new IOException("mark/reset not supported");
  62.     }
  63.  
  64.     public boolean markSupported() {
  65.         return false;
  66.     }
  67.  
  68.     public void readFully(byte value[]) throws IOException {
  69.         readFully(value, 0, value.length);
  70.     }
  71.  
  72.     public void readFully(byte value[], int offset, int length)
  73.         throws IOException {
  74.         booleanCount = INVALID_BUFFER_COUNT;
  75.         int total, count;
  76.         InputStream in = this.in;
  77.  
  78.         total = 0;
  79.  
  80.         while (total < length) {
  81.             count = in.read(value, offset + total, length - total);
  82.             if (count < 0)
  83.                 throw new EOFException();
  84.  
  85.             total += count;
  86.         }
  87.     }
  88.  
  89.     public int skipBytes(int total) throws IOException {
  90.         int orig;
  91.         InputStream in = this.in;
  92.  
  93.         orig = total;
  94.  
  95.         while (total > 0) {
  96.             total -= skip(total);
  97.         }
  98.  
  99.         return orig;
  100.     }
  101.  
  102.     public boolean readCompactBoolean() throws IOException {
  103.         boolean value;
  104.         int buf = booleanBuffer;
  105.         int count = booleanCount;
  106.  
  107.         if (count >= 8) {
  108.             buf = in.read();
  109.             if (buf < 0)
  110.                 throw new EOFException();
  111.  
  112.             count = 0;
  113.         }
  114.  
  115.         value = ((buf & (1 << count)) != 0);
  116.         count++;
  117.  
  118.         booleanBuffer = buf;
  119.         booleanCount = count;
  120.  
  121.         return value;
  122.     }
  123.  
  124.     public boolean readBoolean() throws IOException {
  125.         booleanCount = INVALID_BUFFER_COUNT;
  126.         int c = in.read();
  127.  
  128.         if (c < 0)
  129.             throw new EOFException();
  130.  
  131.         return (c != 0);
  132.     }
  133.  
  134.     public byte readByte() throws IOException {
  135.         booleanCount = INVALID_BUFFER_COUNT;
  136.         int c = in.read();
  137.  
  138.         if (c < 0)
  139.             throw new EOFException();
  140.  
  141.         return (byte)c;
  142.     }
  143.  
  144.     public int readUnsignedByte() throws IOException {
  145.         booleanCount = INVALID_BUFFER_COUNT;
  146.         int c = in.read();
  147.  
  148.         if (c < 0)
  149.             throw new EOFException();
  150.  
  151.         return c;
  152.     }
  153.  
  154.     public short readShort() throws IOException {
  155.         booleanCount = INVALID_BUFFER_COUNT;
  156.         InputStream in = this.in;
  157.         int c1 = in.read();
  158.         int c2 = in.read();
  159.  
  160.         if ((c1 | c2) < 0)
  161.              throw new EOFException();
  162.  
  163.         return (short)((c1 << 8) + (c2 << 0));
  164.     }
  165.  
  166.     public int readUnsignedShort() throws IOException {
  167.         booleanCount = INVALID_BUFFER_COUNT;
  168.         InputStream in = this.in;
  169.         int c1 = in.read();
  170.         int c2 = in.read();
  171.  
  172.         if ((c1 | c2) < 0)
  173.              throw new EOFException();
  174.  
  175.         return (c1 << 8) + (c2 << 0);
  176.     }
  177.  
  178.     public char readChar() throws IOException {
  179.         booleanCount = INVALID_BUFFER_COUNT;
  180.         InputStream in = this.in;
  181.         int c1 = in.read();
  182.         int c2 = in.read();
  183.  
  184.         if ((c1 | c2) < 0)
  185.              throw new EOFException();
  186.  
  187.         return (char)((c1 << 8) + (c2 << 0));
  188.     }
  189.  
  190.     /** This reads in specially packed ints.
  191.       */
  192.     public int readCompactInt() throws IOException {
  193.         booleanCount = INVALID_BUFFER_COUNT;
  194.         InputStream in = this.in;
  195.         int c, value, shift;
  196.         boolean neg;
  197.  
  198.         c = in.read();
  199.         if (c < 0)
  200.             throw new EOFException();
  201.         else if (c == 0x040) {
  202.             return Integer.MIN_VALUE;
  203.         }
  204.  
  205.         neg = (c & 0x40) != 0;
  206.         value = c & 0x3f;
  207.  
  208.         if ((c & 0x80) != 0) {
  209.             c = in.read();
  210.             if (c < 0)
  211.                 throw new EOFException();
  212.  
  213.             value = value | ((c & 0x7f) << 6);
  214.             if ((c & 0x80) != 0) {
  215.                 c = in.read();
  216.                 if (c < 0)
  217.                     throw new EOFException();
  218.  
  219.                 value = value | ((c & 0x7f) << 13);
  220.                 if ((c & 0x80) != 0) {
  221.                     c = in.read();
  222.                     if (c < 0)
  223.                         throw new EOFException();
  224.  
  225.                     value = value | ((c & 0x7f) << 20);
  226.                     if ((c & 0x80) != 0) {
  227.                         c = in.read();
  228.                         if (c < 0)
  229.                             throw new EOFException();
  230.  
  231.                         value = value | ((c & 0x7f) << 27);
  232.                     }
  233.                 }
  234.             }
  235.         }
  236.  
  237.         if (neg)
  238.             value = -value;
  239.  
  240.         return value;
  241.     }
  242.  
  243.     public int readInt() throws IOException {
  244.         booleanCount = INVALID_BUFFER_COUNT;
  245.         InputStream in = this.in;
  246.         int c1 = in.read();
  247.         int c2 = in.read();
  248.         int c3 = in.read();
  249.         int c4 = in.read();
  250.  
  251.         if ((c1 | c2 | c3 | c4) < 0)
  252.              throw new EOFException();
  253.  
  254.         return ((c1 << 24) + (c2 << 16) + (c3 << 8) + (c4 << 0));
  255.     }
  256.  
  257.     public long readLong() throws IOException {
  258.         return (((long)readInt()) << 32L) + (((long)readInt()) & 0xffffffffL);
  259.     }
  260.  
  261.     public float readFloat() throws IOException {
  262.         return Float.intBitsToFloat(readInt());
  263.     }
  264.  
  265.     public double readDouble() throws IOException {
  266.         return Double.longBitsToDouble(readLong());
  267.     }
  268.  
  269.     public String readCompactUTF() throws IOException {
  270.         int id;
  271.         String str;
  272.  
  273.         id = readCompactInt();
  274.  
  275.         // There are two special ids for null and "".
  276.  
  277.         if (id == 0) {
  278.             return null;
  279.         } else if (id == 1) {
  280.             return "";
  281.         }
  282.  
  283.         // If the id is less than zero then this is a new string and the
  284.         // absolute value is the length of the string.
  285.  
  286.         if (id < 0) {
  287.             str = readUTFBytes(-id);
  288.             stringVector.addElement(str);
  289.             return str;
  290.         }
  291.  
  292.         // We need to subtract 2 because of the special ids.
  293.  
  294.         return (String)stringVector.elementAt(id - 2);
  295.     }
  296.  
  297.     public String readUTF() throws IOException {
  298.         int utflen;
  299.  
  300.         utflen = readUnsignedShort();
  301.         if (utflen == 0xffff)
  302.             return null;
  303.  
  304.         return readUTFBytes(utflen);
  305.     }
  306.  
  307.     private final String readUTFBytes(int utflen) throws IOException {
  308.         booleanCount = INVALID_BUFFER_COUNT;
  309.         char str[] = new char[utflen];
  310.         int count = 0;
  311.         int strlen = 0;
  312.  
  313.         while (count < utflen) {
  314.             int c = readUnsignedByte();
  315.             int char2, char3;
  316.             switch (c >> 4) {
  317.                 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
  318.                     // 0xxxxxxx
  319.                     count++;
  320.                     str[strlen++] = (char)c;
  321.                     break;
  322.                 case 12: case 13:
  323.                     // 110x xxxx   10xx xxxx
  324.                     count += 2;
  325.                     if (count > utflen)
  326.                         throw new UTFDataFormatException();
  327.                     char2 = readUnsignedByte();
  328.                     if ((char2 & 0xC0) != 0x80)
  329.                         throw new UTFDataFormatException();
  330.                     str[strlen++] = (char)(((c & 0x1F) << 6) | (char2 & 0x3F));
  331.                     break;
  332.                 case 14:
  333.                     // 1110 xxxx  10xx xxxx  10xx xxxx
  334.                     count += 3;
  335.                     if (count > utflen)
  336.                         throw new UTFDataFormatException();
  337.                     char2 = readUnsignedByte();
  338.                     char3 = readUnsignedByte();
  339.                     if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
  340.                         throw new UTFDataFormatException();
  341.                     str[strlen++] = (char)(((c & 0x0F) << 12) |
  342.                                            ((char2 & 0x3F) << 6) |
  343.                                            ((char3 & 0x3F) << 0));
  344.                 default:
  345.                     // 10xx xxxx,  1111 xxxx
  346.                     throw new UTFDataFormatException();
  347.                 }
  348.         }
  349.  
  350.         return new String(str, 0, strlen);
  351.     }
  352. }
  353.